﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml;
using System.IO;
using XmlDSigEx;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;

namespace TestCustomSigning
{
    [TestClass]
    public class TestXPathFilter
    {
    private const string input = @"<Document>
     <ToBeSigned>
       <!-- comment -->
       <Data />
       <NotToBeSigned>
         <ReallyToBeSigned>
           <!-- comment -->
           <Data />
         </ReallyToBeSigned>
       </NotToBeSigned>
     </ToBeSigned>
     <ToBeSigned>
       <Data />
       <NotToBeSigned>
         <Data />
       </NotToBeSigned>
     </ToBeSigned>
    </Document>";

        
    
        [TestMethod]
        public void TestMixedFilters()
        {
            XmlDocument doc = new XmlDocument() { PreserveWhitespace = true };
            XmlReader reader = XmlReader.Create(new StringReader(input));
            doc.Load(reader);

            XmlSigner signer = new XmlSigner(doc);
            signer.CanonicalisationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
            signer.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";

            XmlDSigEx.Reference refr = signer.CreateReference();
            refr.Uri = "";
            refr.DigestMethod = SignedXml.XmlDsigSHA1Url;
            XPathFilter2Transform transform1 = refr.AddTransform(XPathFilter2Transform.URI_XPATH2TRANSFORM) as XPathFilter2Transform;
            var exp1 = transform1.AddExpression(FilterType.Intersect, "//ToBeSigned");
            transform1.AddExpression(FilterType.Subtract, "//NotToBeSigned");
            transform1.AddExpression(FilterType.Union, "//ReallyToBeSigned");

            var cert = new X509Certificate2(TestSigner.GetEmbeddedBytes("TestCustomSigning.testcert.pfx"), "password");

            RSAX509Algorithm algorithm = new RSAX509Algorithm(cert);
            algorithm.KeyInfo = X509Data.X509Certificate;

            var element = signer.GetXml(algorithm);
            string output = element.OuterXml;

            doc.DocumentElement.AppendChild(doc.ImportNode(element, true));

            string signed = doc.OuterXml;
            XmlDocument signedDoc = new XmlDocument() { PreserveWhitespace = true };
            signedDoc.Load(XmlReader.Create(new StringReader(signed)));

            XmlSigner verifier = new XmlSigner(signedDoc);
            ISignatureAlgorithm algorithm2 = new RSAX509Algorithm(cert);
            bool result = verifier.ValidateSignature(signedDoc.DocumentElement.LastChild as XmlElement, algorithm);
            Assert.IsTrue(result);
        }

        [TestMethod]
        public void TestAcrobatSample()
        {
            string input = TestSigner.GetEmbeddedContent("TestCustomSigning.AcrobatSignature.xml");

            XmlDocument signedDoc = new XmlDocument() { PreserveWhitespace = true };
            signedDoc.Load(XmlReader.Create(new StringReader(input)));


            XmlSigner signer = new XmlSigner(signedDoc);
            bool result = signer.ValidateSignature(signedDoc.DocumentElement.LastChild.LastChild as XmlElement);
            Assert.IsTrue(result);
        }

        [TestMethod]
        [Ignore]
        public void TestAcrobatSampleSignAndVerify()
        {
            string input = TestSigner.GetEmbeddedContent("TestCustomSigning.AcrobatInput.xml");
            XmlDocument doc = new XmlDocument() { PreserveWhitespace = true };
            XmlReader reader = XmlReader.Create(new StringReader(input));
            doc.Load(reader);

            XmlSigner signer = new XmlSigner(doc);
            signer.CanonicalisationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
            signer.SignatureMethod = "http://www.w3.org/2001/04/xmldsig#rsa-sha1";

            XmlDSigEx.Reference refr = signer.CreateReference();
            refr.Uri = "#id8086b35e-c0b1-11df-8479-005056b245fe";
            refr.DigestMethod = SignedXml.XmlDsigSHA1Url;
            refr.AddTransform(SignedXml.XmlDsigExcC14NWithCommentsTransformUrl);

            XmlDSigEx.Reference refr2 = signer.CreateReference();
            refr2.Uri = "";
            refr2.DigestMethod = SignedXml.XmlDsigSHA1Url;

            XPathFilter2Transform transform = (XPathFilter2Transform)refr2.AddTransform(XPathFilter2Transform.URI_XPATH2TRANSFORM);
            XPathFilter2Expression expression = transform.AddExpression(FilterType.Subtract, "here()/ancestor::ds:Signature[1]");
            expression.AddNamespace("ds", XmlSigner.NS_XMLDSIG);
            refr2.AddTransform(SignedXml.XmlDsigExcC14NWithCommentsTransformUrl);



            var cert = new X509Certificate2(TestSigner.GetEmbeddedBytes("TestCustomSigning.testcert.pfx"), "password");

            RSAX509Algorithm algorithm = new RSAX509Algorithm(cert);
            algorithm.KeyInfo = X509Data.X509Certificate;

            var element = signer.GetXml(algorithm);
            string output = element.OuterXml;

            doc.DocumentElement.AppendChild(doc.ImportNode(element, true));

            string signed = doc.OuterXml;
            XmlDocument signedDoc = new XmlDocument() { PreserveWhitespace = true };
            signedDoc.Load(XmlReader.Create(new StringReader(signed)));

            XmlSigner verifier = new XmlSigner(signedDoc);
            ISignatureAlgorithm algorithm2 = new RSAX509Algorithm(cert);
            bool result = verifier.ValidateSignature(signedDoc.DocumentElement.LastChild as XmlElement, algorithm);
            Assert.IsTrue(result);
        }
    }
}
